# -*- coding: utf-8 -*-
from openerp.osv import fields
from openerp.osv import osv
from openerp import SUPERUSER_ID

class create_stock_exchange(osv.osv_memory):
    _name = 'create.stock.exchange'

    def on_change_prodcut_id_num(self, cr, uid, ids, product_id, number, location_id,context=None):
        bom_detail_message = "<table class='oe_webclient'><tr><td>产品</td><td>数量</td><td>库存</td></tr>"
        if number > 0 and product_id and location_id:
            product_row = self.pool.get('product.product').browse(cr,uid,product_id,context=context)
            mrp_bom_id = self.pool.get('mrp.bom').search(
                cr, uid, [('product_tmpl_id', '=', product_row.product_tmpl_id.id)], context=context)
            mrp_bom_obj = self.pool.get('mrp.bom').browse(
                cr, uid, mrp_bom_id, context=context)
            if not mrp_bom_obj:
                return {'warning': {'title': u'错误', 'message': u"您选的产品还没有建立BOM单"},
                        'value': {'product_bom_detail_messaege': '', 'product_id': ''}}
            if not mrp_bom_obj.bom_line_ids:
                return {'warning': {'title': u'错误', 'message': u"您选的产品BOM单为空"},
                        'value': {'product_bom_detail_messaege': '', 'product_id': ''}}
            product_dict, location_qty_dict = {}, {}
            for bom in mrp_bom_obj.bom_line_ids:
                product_dict.update({bom.product_id.id: [bom.product_id.name, bom.product_qty, mrp_bom_obj.product_qty]})
            cr.execute("""SELECT product_id AS product_id,
                                      sum(qty) as qty 
                                      from stock_quant where product_id in %s and reservation_id is NULL
                                      AND location_id = %s 
                                      group by product_id
                                      """ % (str(list(product_dict.keys())).replace('[', '(').replace(']', ')'),
                                             location_id))
            location_qty_list = cr.dictfetchall()
            [location_qty_dict.update({location_qty.get('product_id'): location_qty.get('qty')}) for location_qty in location_qty_list]
            for product_id, product_list in product_dict.items():
                bom_detail_message = bom_detail_message + u"<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (
                    product_list[0], product_list[1] * number / product_list[2], location_qty_dict.get(product_id))
            bom_detail_message += "</table>"
            return {'value': {'product_bom_detail_messaege': bom_detail_message}}

    def create_stock_exchange_function(self, cr, uid, ids, context=None):
        create_stock_data = self.browse(cr, uid, ids, context=context)
        no_type_stock_change = self.pool.get("stock.change")
        no_data_stock_move = self.pool.get('stock.move')
        mrp_bom_id = self.pool.get('mrp.bom').search(
            cr, uid, [('product_tmpl_id', '=', create_stock_data.product_id.product_tmpl_id.id)], context=context)
        mrp_bom_obj = self.pool.get('mrp.bom').browse(
            cr, uid, mrp_bom_id, context=context)
        model_data_obj = self.pool.get('ir.model.data')
        location_production_location_id = model_data_obj.xmlid_to_res_id(
            cr, SUPERUSER_ID, 'stock.location_production')
        stock_location_stock_id = create_stock_data.location_id.id or model_data_obj.xmlid_to_res_id(
            cr, SUPERUSER_ID, 'stock.stock_location_stock')

        manufacturing_type_id = model_data_obj.xmlid_to_res_id(
            cr, SUPERUSER_ID, 'osbzr_stock_change_ext.manufacturing_picking_type')
        stock_change_id = no_type_stock_change.create(cr, uid,
                                                      {'location_id': stock_location_stock_id,
                                                       'type': 'split'  if create_stock_data.exchange_type == '拆分' else 'combination', 
                                                       'location_dest_id':location_production_location_id },
                                                      context=context)
        if create_stock_data.exchange_type == '拆分':
            no_data_stock_move.create(cr, uid, {'product_id': create_stock_data.product_id.id,
                                                'product_uom_qty': create_stock_data.number,
                                                'location_id': stock_location_stock_id,
                                                'location_dest_id': location_production_location_id,
                                                'raw_material_change_id': stock_change_id,
                                                "name": create_stock_data.product_id.name,
                                                "product_uom": create_stock_data.product_id.uom_id.id,
                                                'picking_type_id': manufacturing_type_id}, context=context)
            for bom in mrp_bom_obj.bom_line_ids:
                no_data_stock_move.create(cr, uid, {'product_id': bom.product_id.id,
                                                    'product_uom_qty': bom.product_qty * create_stock_data.number / mrp_bom_obj.product_qty,
                                                    'location_id':  location_production_location_id,
                                                    'location_dest_id':stock_location_stock_id,
                                                    'change_id': stock_change_id, "name": bom.product_id.name,
                                                    "product_uom": bom.product_id.uom_id.id,
                                                    'picking_type_id': manufacturing_type_id}, context=context)
        else:
            no_data_stock_move.create(cr, uid, {'product_id': create_stock_data.product_id.id,
                                                'product_uom_qty': create_stock_data.number,
                                                'location_id': location_production_location_id,
                                                'location_dest_id': stock_location_stock_id,
                                                'change_id': stock_change_id, "name": create_stock_data.product_id.name,
                                                "product_uom": create_stock_data.product_id.uom_id.id,
                                                'picking_type_id': manufacturing_type_id}, context=context)
            for bom in mrp_bom_obj.bom_line_ids:
                no_data_stock_move.create(cr, uid, {'product_id': bom.product_id.id,
                                                    'product_uom_qty': bom.product_qty * create_stock_data.number / mrp_bom_obj.product_qty,
                                                    'location_id': stock_location_stock_id,
                                                    'location_dest_id': location_production_location_id,
                                                    'raw_material_change_id': stock_change_id,
                                                    "name": bom.product_id.name,
                                                    "product_uom": bom.product_id.uom_id.id,
                                                    'picking_type_id': manufacturing_type_id}, context=context)
        no_type_stock_change.action_submit(
            cr, uid, [stock_change_id], context=context)
        no_type_stock_change.action_approve(
            cr, uid, [stock_change_id], context=context)

        mod_obj = self.pool.get('ir.model.data')
        act_obj = self.pool.get('ir.actions.act_window')
        result = mod_obj.get_object_reference(
            cr, uid, 'osbzr_stock_change', 'action_stock_change_account_move')
        id = result and result[1] or False
        result = act_obj.read(cr, uid, [id], context=context)[0]
        res = mod_obj.get_object_reference(
            cr, uid, 'osbzr_stock_change', 'stock_change_form')
        result['views'] = [(res and res[1] or False, 'form')]
        result['res_id'] = stock_change_id
        return result

    _columns = {
        'exchange_type': fields.selection([(u'拆分', u'拆分'), (u'组合', u'组合')], string='操作类型'),
        'number': fields.integer(u'数量'),
        'product_id': fields.many2one('product.product', string='产品', required=True),
        'location_id': fields.many2one('stock.location', string='库位'),
        'product_bom_detail_messaege': fields.html(string='BOM产品详细信息'),
    }
    _defaults = {
        'number': 1,
        'exchange_type': u'组合'
    }


class stock_change(osv.osv):
    _inherit = 'stock.change'
    _columns = {
        'in_product_id': fields.related('move_in_lines', 'product_id', type='many2one', string="入库产品",
                                        relation='product.product', store=True), 
        'out_product_id': fields.related('move_out_lines', 'product_id', type='many2one', string="出库产品", 
                                         relation='product.product', store=True),
        'type': fields.selection([('split', u'拆分'), ('combination', u'组合')], string="类型"),   
        'stock_picking_id': fields.many2one('stock.picking', string='出库单')
    }

    def unlink(self, cr, uid, ids, context=None):
        for change_row in self.browse(cr, uid, ids, context=context):
            if change_row.state == 'done':
                raise osv.except_osv(u'错误!', '完成状态不能删除！')
            for move in change_row.move_in_lines:
                if move.state == 'draft':
                    move.unlink()
                elif move.state in ('assigned', 'waiting', 'confirmed'):
                    move.action_cancel()
                    move.unlink()
            for move in change_row.move_out_lines:
                if move.state == 'draft':
                    move.unlink()
                elif move.state in ('assigned', 'waiting', 'confirmed'):
                    move.action_cancel()
                    move.unlink()
        return super(stock_change, self).unlink(cr, uid, ids, context=context)
        

class stock_picking(osv.osv):
    _inherit = 'stock.picking'

    def get_product_location_available_qty(self, cr, uid, product_ids, context=None):
        """根据参数 产品的ids 和库位的信息 查找到 对应库位的产品的数量 返回结果是 {'produc_id':'qty'} de 形式"""
        res = {}
        cr.execute("""SELECT product_id AS product_id,
                      sum(qty) as qty,
                      location_id as location_id
                      from stock_quant where product_id in %s and  reservation_id is NULL
                      group by product_id,location_id
                      """ % (str(product_ids).replace('[', '(').replace(']', ')')))
        available_qty = cr.dictfetchall()
        map(lambda x: res.setdefault((x.get('product_id'), x.get('location_id')), x.get('qty')),available_qty)
        return res

    def get_child_location_ids(self, cr, uid, location_id, context=None):
        """ 获取仓库 对应的子仓库的所有的 库存数！"""
        location_obj= self.pool.get('stock.location')
        location_ids = location_obj.search(cr, uid, [('location_id', '=', location_id)], context=context)
        return_location_ids = [location_id]
        while location_ids:
            return_location_ids += location_ids
            location_ids = location_obj.search(cr, uid, [('location_id', 'in', location_ids)], context=context)
        return return_location_ids

    # 根据可用库存数, 取得需要转换的数量
    def get_need_conversion_num(self, cr, uid, product_id, location_id, qty, context=None):
        product_location_dict = self.get_product_location_available_qty(cr, uid, [product_id], context=context)
        location_ids = self.get_child_location_ids(cr, uid, location_id, context=context)
        available_without_reservation = sum(
            [product_location_dict.get((product_id, location_id), 0) for location_id in location_ids]
        )
        return qty - available_without_reservation

    # 重载检查可用
    # 当产品是bom产品的时候, 取得库存需要数, 进行库存转换
    # 当bom类型为套件时, 销售出库单move产品会被odoo自动拆分好, 也就是已经是配件了, 不回触发本代码
    # 当bom类型为普通时, 会触发本代码
    # 卡券提货订单锁定的时候， action_assign
    # def action_assign(self, cr, uid, ids, context=None):
    #     bom_obj = self.pool.get('mrp.bom')
    #     for picking in self.browse(cr,uid,ids,context=context):
    #         for move in picking.move_lines:
    #             product_id = move.product_id.id
    #             bom_id = bom_obj.search(cr, uid, [('product_tmpl_id', '=', move.product_id.product_tmpl_id.id)], context=context)
    #             if bom_id:
    #                 need_conversion_num = self.get_need_conversion_num(cr, uid, product_id, move.location_id.id,
    #                                                                move.product_uom_qty, context=context)
    #                 if need_conversion_num > 0:
    #                     self.create_bom_conversion_form(cr, uid, move.product_id.id, need_conversion_num,
    #                                                     move.location_id.id, picking.id, context=context)
    #     try:
    #         return super(stock_picking, self).action_assign(cr, uid, ids, context=context)
    #     except Exception as e:
    #         if e and e[1] == u'没有要检查的有效性。':
    #             return False
    #         else:
    #             raise osv.except_osv(*e)

    # 建立库存转换单
    def create_bom_conversion_form(self, cr, uid, product_id, qty, location_id, picking_id, context=None):
        exchange_obj = self.pool.get('create.stock.exchange')
        create_vals = {'product_id': product_id, 'number': qty, 'exchange_type': u'组合', 'location_id': location_id}
        exchange_id = exchange_obj.create(cr, uid, create_vals, context=context)
        stock_exchange_form = exchange_obj.create_stock_exchange_function(cr, uid, exchange_id, context=context)
        self.pool.get('stock.change').write(cr, uid, stock_exchange_form.get('res_id'),
                                            {'stock_picking_id': picking_id}, context=context)
        return True

    